import { Request, RequestHandler, Response } from "express";
import {
  IGetProjectByIdReq,
  IGetProjectByProjectIdReq,
  IGetProjectByStatusReq,
  IGetProjectByOwnerReq,
  IGetProjectByUserReq,
  IAddProjectReq,
  IUpdateProjectReq,
  IDeleteProjectReq,
  IGetProjectByGroupIdReq,
  IProject,
} from "../../models/project.model";
import * as ProjectService from "../services/project.service";
import * as ProjectChangeService from "../services/project-change.service";
import * as ResearchGroupService from "../services/research-group.service";
import { convertToLocalDateString } from "../utils/date";
import { generateProjectId } from "../utils/utils";
import fs from "fs";
import { IncomingForm } from "formidable";
import { getCurrentDate } from "../utils/date";

/**
 * Get active project records
 *
 * @param req Express Request
 * @param res Express Response
 */
export const getProjects: RequestHandler = async (
  req: Request,
  res: Response
) => {
  try {
    const projects = await ProjectService.getProjects();

    res.status(200).json({
      data: projects,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][getProjects][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "项目信息列表获取失败！",
    });
  }
};

/**
 * Get active mid project records
 *
 * @param req Express Request
 * @param res Express Response
 */
export const getSubjectProjectChecks: RequestHandler = async (
  req: Request,
  res: Response
) => {
  try {
    const midProjects = await ProjectService.getSubjectProjectChecks();

    res.status(200).json({
      data: midProjects,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projectChecks.controller][getSubjectProjectChecks][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "开题项目列表获取失败！",
    });
  }
};
/**
 * Get active mid project records
 *
 * @param req Express Request
 * @param res Express Response
 */
export const getMidProjectChecks: RequestHandler = async (
    req: Request,
    res: Response
) => {
  try {
    const midProjects = await ProjectService.getMidProjectChecks();

    res.status(200).json({
      data: midProjects,
      code: 2000,
    })
  } catch (error) {
    console.error(
        "[projectChecks.controller][getMidProjectChecks][Error] ",
        typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "中检项目列表获取失败！",
    });
  }
};
/**
 * Get active final project check records
 *
 * @param req Express Request
 * @param res Express Response
 */
export const getFinalProjectChecks: RequestHandler = async (
  req: Request,
  res: Response
) => {
  try {
    const finalProjects = await ProjectService.getFinalProjectChecks();

    res.status(200).json({
      data: finalProjects,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projectChecks.controller][getFinalCheckProjects][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "结项项目列表获取失败！",
    });
  }
};

/**
 * Get notified mid&final project records
 *
 * @param req Express Request
 * @param res Express Response
 */
export const getNotifiedProjects: RequestHandler = async (
  req: Request,
  res: Response
) => {
  try {
    const midProjects = await ProjectService.getNotifiedMidProjects();
    const finalProjects = await ProjectService.getNotifiedFinalProjects();


    res.status(200).json({
      data: {
        mid: midProjects,
        final: finalProjects
      },
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][getProjects][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "项目信息列表获取失败！",
    });
  }
};

/**
 * Get project record based on id provided
 *
 * @param req Express Request
 * @param res Express Response
 */
// @ts-ignore
export const getProjectById: RequestHandler = async (
  req: IGetProjectByIdReq,
  res: Response
) => {
  try {
    const project = await ProjectService.getProjectById(req.params.id);

    res.status(200).json({
      data: project,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][getProjectById][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "项目信息获取失败！",
    });
  }
};

/**
 * Get project record based on project id provided
 *
 * @param req Express Request
 * @param res Express Response
 */
// @ts-ignore
export const getProjectByProjectId: RequestHandler = async (
  req: IGetProjectByProjectIdReq,
  res: Response
) => {
  try {
    const project = await ProjectService.getProjectByProjectId(
      req.params.projectId
    );

    res.status(200).json({
      data: project,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][getProjectById][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "项目信息获取失败！",
    });
  }
};

/**
 * Get project record based on group id provided
 *
 * @param req Express Request
 * @param res Express Response
 */
// @ts-ignore
export const GetProjectsByGroupId: RequestHandler = async (
  req: IGetProjectByGroupIdReq,
  res: Response
) => {
  try {
    const project = await ProjectService.GetProjectsByGroupId(
      req.params.projectGroupId
    );

    res.status(200).json({
      data: project,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][getProjectById][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "项目信息获取失败！",
    });
  }
};

/**
 * Get project record based on status provided
 *
 * @param req Express Request
 * @param res Express Response
 */
// @ts-ignore
export const getProjectsByStatus: RequestHandler = async (
  req: IGetProjectByStatusReq,
  res: Response
) => {
  try {
    const projects = await ProjectService.getProjectsByStatus(
      req.params.projectStatus.split(',')
    );
    res.status(200).json({
      data: projects,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][getProjectById][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "项目信息列表获取失败！",
    });
  }
};

/**
 * Get project record based on owner provided
 *
 * @param req Express Request
 * @param res Express Response
 */
// @ts-ignore
export const getProjectsByOwnerId: RequestHandler = async (
  req: IGetProjectByOwnerReq,
  res: Response
) => {
  try {
    const projects = await ProjectService.getProjectsByOwnerId(
      req.params.projectOwnerId
    );

    res.status(200).json({
      data: projects,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][getProjectById][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "项目信息列表获取失败！",
    });
  }
};

/**
 * Get project record based on applicant provided
 *
 * @param req Express Request
 * @param res Express Response
 */
// @ts-ignore
export const getProjectsByUserId: RequestHandler = async (
  req: IGetProjectByUserReq,
  res: Response
) => {
  try {
    let participatedProjects: IProject[] =[];
    let owenedProjects: IProject[] =[];

    const owenResearchGroups = await ResearchGroupService.getResearchGroupByOwnerId(req.params.id);
    const groupIds: number[] = [];
    if (owenResearchGroups && owenResearchGroups.length > 0) {
      owenResearchGroups.map(group => {
        groupIds.push(group.id);
      })
      if (groupIds.length > 0) {
        owenedProjects = await ProjectService.getProjectsByGroupIds(groupIds)
      }
    }

    const allGroups = await ResearchGroupService.getResearchGroups();
    const participateGroupIds: number[] = [];
    const participatedGroups: any[]=[];
    allGroups.forEach((group) => {
      const members = group.researchGroupMembers?.length > 0
                ? JSON.parse(group.researchGroupMembers as unknown as string)
                : [];
      let isIn = false;
      members.forEach((item: any) => {
        if (req.params.id === (item as any).researchGroupMemberId.toString() && !groupIds.includes(group.id)) {
          isIn = true;
        }
      })
      if (isIn) {
        participatedGroups.push(group);
        participateGroupIds.push(group.id)
      }
    })  
    
    if (participateGroupIds && participateGroupIds.length > 0) {
      participatedProjects = await ProjectService.getProjectsByGroupIds(participateGroupIds)
    }

    res.status(200).json({
      data: {
        applied: owenedProjects,
        participated: participatedProjects
      },
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][getProjectById][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "项目信息列表获取失败！",
    });
  }
};

/**
 * Get new projectid
 * @param req Express Request
 * @param res Express Response
 */
// @ts-ignore
export const getProjectId: RequestHandler = async (
  req: IGetProjectByUserReq,
  res: Response
) => {
  try {
    const lastProject = await ProjectService.getLastProject();
    new Date().getFullYear()
    let projectId = '';
    if (lastProject && lastProject.length > 0 && lastProject[0].projectMaxId) {
        projectId = generateProjectId(lastProject[0].projectMaxId);
    }
    projectId = `${new Date().getFullYear()}00001`;

    res.status(200).json({
      data: projectId,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][getProjectId][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "获取新项目编号失败！",
    });
  }
};

/**
 * Inserts a new project record
 *
 * @param req Express Request
 * @param res Express Response
 */
export const addProject: RequestHandler = async (
  req: IAddProjectReq,
  res: Response
) => {
  try {
    req.body.projectDeclareDate = req.body.projectDeclareDate
      ? convertToLocalDateString(req.body.projectDeclareDate)
      : null;
    req.body.projectCreatedDate = req.body.projectCreatedDate
      ? convertToLocalDateString(req.body.projectCreatedDate)
      : null;
    req.body.projectStartDate = req.body.projectStartDate
      ? convertToLocalDateString(req.body.projectStartDate)
      : null;
    req.body.projectExpectedEndDate = req.body.projectExpectedEndDate
      ? convertToLocalDateString(req.body.projectExpectedEndDate)
      : null;
    req.body.projectEndDate = req.body.projectEndDate
      ? convertToLocalDateString(req.body.projectEndDate)
      : null;
    // projectSubjectDate
    req.body.projectSubjectDate = req.body.projectSubjectDate
        ? convertToLocalDateString(req.body.projectSubjectDate)
        : null;
    req.body.projectSubjectDate = req.body.projectSubjectDate
      ? convertToLocalDateString(req.body.projectSubjectDate)
      : null;
    req.body.projectMidDate = req.body.projectMidDate
        ? convertToLocalDateString(req.body.projectMidDate)
        : null;
    req.body.projectFinalDate = req.body.projectFinalDate
      ? convertToLocalDateString(req.body.projectFinalDate)
      : null;

    req.body.projectAppliedCostItems =
      req.body.projectAppliedCostItems?.length > 0
        ? JSON.stringify(req.body.projectAppliedCostItems)
        : null;
    let data = {}
    for (const bodyKey in req.body) {
      if (req.body[bodyKey]) {
        // @ts-ignore
        data[bodyKey] = req.body[bodyKey]
      }
    }
    const result = await ProjectService.insertProject(<IProject>data);

    res.status(200).json({
      data: result,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][addProject][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    if (error.code === "ER_DUP_ENTRY") {
      res.status(500).json({
        message: "项目编号已存在！",
      });
    } else {
      res.status(500).json({
        message: "项目信息保存失败！",
      });
    }
  }
};


/**
 * Updates project approve record
 *
 * @param req Express Request
 * @param res Express Response
 */
// @ts-ignore
export const updateProjectApproveById: RequestHandler = async (
  req: IUpdateProjectReq,
  res: Response
) => {
  try {
    req.body.projectForm.projectApprovedCost = req.body.projectForm.projectApprovedCost? 
      Number(req.body.projectForm.projectApprovedCost) : req.body.projectForm.projectApprovedCost;
    req.body.projectForm.projectDeclareDate = req.body.projectForm.projectDeclareDate
      ? req.body.projectForm.projectDeclareDate.length === 10 ?req.body.projectForm.projectDeclareDate : convertToLocalDateString(req.body.projectForm.projectDeclareDate)
      : null;
    req.body.projectForm.projectCreatedDate = req.body.projectForm.projectCreatedDate
      ? req.body.projectForm.projectCreatedDate.length === 10 ?req.body.projectForm.projectCreatedDate : convertToLocalDateString(req.body.projectForm.projectCreatedDate)
      : null;
    req.body.projectForm.projectStartDate = req.body.projectForm.projectStartDate
      ? req.body.projectForm.projectStartDate.length === 10 ?req.body.projectForm.projectStartDate : convertToLocalDateString(req.body.projectForm.projectStartDate)
      : null;
    req.body.projectForm.projectExpectedEndDate = req.body.projectForm.projectExpectedEndDate
      ? req.body.projectForm.projectExpectedEndDate.length === 10 ?req.body.projectForm.projectExpectedEndDate : convertToLocalDateString(req.body.projectForm.projectExpectedEndDate)
      : null;
    req.body.projectForm.projectEndDate = req.body.projectForm.projectEndDate
      ? req.body.projectForm.projectEndDate.length === 10 ?req.body.projectForm.projectEndDate : convertToLocalDateString(req.body.projectForm.projectEndDate)
      : null;
    req.body.projectForm.projectSubjectDate = req.body.projectForm.projectSubjectDate
      ? req.body.projectForm.projectSubjectDate.length === 10 ?req.body.projectForm.projectSubjectDate : convertToLocalDateString(req.body.projectForm.projectSubjectDate)
      : null;
    req.body.projectForm.projectMidDate = req.body.projectForm.projectMidDate
        ? req.body.projectForm.projectMidDate.length === 10 ?req.body.projectForm.projectMidDate : convertToLocalDateString(req.body.projectForm.projectMidDate)
        : null;
    req.body.projectForm.projectFinalDate = req.body.projectForm.projectFinalDate
      ? req.body.projectForm.projectFinalDate.length === 10 ?req.body.projectForm.projectFinalDate : convertToLocalDateString(req.body.projectForm.projectFinalDate)
      : null;

    req.body.projectForm.projectAppliedCostItems =
      typeof(req.body.projectForm.projectAppliedCostItems) === 'object'
      ? JSON.stringify(req.body.projectForm.projectAppliedCostItems)
      : null;
    req.body.projectForm.projectCheckHistory =
    typeof(req.body.projectForm.projectCheckHistory) === 'object'
        ? JSON.stringify(req.body.projectForm.projectCheckHistory)
          : null;
    req.body.projectForm.projectChangeHistory = 
    typeof(req.body.projectForm.projectChangeHistory) === 'object'
        ? JSON.stringify(req.body.projectForm.projectChangeHistory)
        : null;

    req.body.projectForm.projectInformationCheckHistory =
    typeof(req.body.projectForm.projectInformationCheckHistory) === 'object'
          ? JSON.stringify(req.body.projectForm.projectInformationCheckHistory)
            : null;

    const cacheProjectMembers = req.body.changeForm?.projectMembers;

    let changeResult: boolean;

    if (req.body.isChange) {
      req.body.changeForm.projectChangeRequestDate = getCurrentDate();
      req.body.changeForm.projectCreatedDate = req.body.changeForm.projectCreatedDate
      ? req.body.changeForm.projectCreatedDate.length === 10 ?req.body.changeForm.projectCreatedDate : convertToLocalDateString(req.body.changeForm.projectCreatedDate)
      : null;
      req.body.changeForm.projectStartDate = req.body.changeForm.projectStartDate
      ? req.body.changeForm.projectStartDate.length === 10 ?req.body.changeForm.projectStartDate : convertToLocalDateString(req.body.changeForm.projectStartDate)
      : null;
      req.body.changeForm.projectExpectedEndDate = req.body.changeForm.projectExpectedEndDate
      ? req.body.changeForm.projectExpectedEndDate.length === 10 ?req.body.changeForm.projectExpectedEndDate : convertToLocalDateString(req.body.changeForm.projectExpectedEndDate)
      : null;
      req.body.changeForm.projectChangeRequestDate = req.body.changeForm.projectEndDate
      ? req.body.changeForm.projectEndDate.length === 10 ?req.body.changeForm.projectEndDate : convertToLocalDateString(req.body.changeForm.projectEndDate)
      : null;
      req.body.changeForm.projectReviewerDate = req.body.changeForm.projectReviewerDate
      ? req.body.changeForm.projectReviewerDate.length === 10 ?req.body.changeForm.projectReviewerDate : convertToLocalDateString(req.body.changeForm.projectReviewerDate)
      : null;
      req.body.changeForm.projectAppliedCostItems =
        typeof(req.body.changeForm.projectAppliedCostItems) === 'object'
        ? JSON.stringify(req.body.changeForm.projectAppliedCostItems)
        : null;
      req.body.changeForm.projectMembers =
        typeof(req.body.changeForm.projectMembers) === 'object'
          ? JSON.stringify(req.body.changeForm.projectMembers)
          : null;
          
      changeResult = await ProjectChangeService.updateProjectChange({...req.body.changeForm, id: req.body.changeForm.id}
        );
      const existingPendingChange = await ProjectChangeService.GetInProgressProjectChangesByPId(req.body.changeForm.pId);
      req.body.projectForm.projectChangeStatus = existingPendingChange && existingPendingChange.length > 0?
        "项目变更审批中" : "项目变更审批结束";
    }

    const projectResult = await ProjectService.updateProject({
      ...req.body.projectForm,
      id: req.params.id,
    });

    if (projectResult && changeResult && req.body.isMemberChange) {
      const researchGroup = await ResearchGroupService.getResearchGroupById(req.body.projectForm.projectGroupId);
      (researchGroup[0] as any).updatedTime = new Date(Date.now());
      (researchGroup[0] as any).researchGroupMembers = req.body.changeForm.projectMembers?.length > 0? req.body.changeForm.projectMembers : "";
      const researchGroupId = researchGroup[0].id;
      delete researchGroup[0].id;
      const result = await ResearchGroupService.updateResearchGroup({
      ...researchGroup[0],
      id: researchGroupId,
     });
    }

    res.status(200).json({
      data: projectResult,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][updateProjectById][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    if (error.code === "ER_DUP_ENTRY") {
      res.status(500).json({
        message: "项目名称重复，请重新输入！",
      });
    } else {
      res.status(500).json({
        message: "项目信息更新失败！",
      });
    }
  }
};

/**
 * Updates existing project record
 *
 * @param req Express Request
 * @param res Express Response
 */
// @ts-ignore
export const updateProjectById: RequestHandler = async (
  req: IUpdateProjectReq,
  res: Response
) => {
  try {
    req.body.projectDeclareDate = req.body.projectDeclareDate
      ? req.body.projectDeclareDate.length === 10 ?req.body.projectDeclareDate : convertToLocalDateString(req.body.projectDeclareDate)
      : null;
    req.body.projectCreatedDate = req.body.projectCreatedDate
      ? req.body.projectCreatedDate.length === 10 ?req.body.projectCreatedDate : convertToLocalDateString(req.body.projectCreatedDate)
      : null;
    req.body.projectStartDate = req.body.projectStartDate
      ? req.body.projectStartDate.length === 10 ?req.body.projectStartDate : convertToLocalDateString(req.body.projectStartDate)
      : null;
    req.body.projectExpectedEndDate = req.body.projectExpectedEndDate
      ? req.body.projectExpectedEndDate.length === 10 ?req.body.projectExpectedEndDate : convertToLocalDateString(req.body.projectExpectedEndDate)
      : null;
    req.body.projectEndDate = req.body.projectEndDate
      ? req.body.projectEndDate.length === 10 ?req.body.projectEndDate : convertToLocalDateString(req.body.projectEndDate)
      : null;
    req.body.projectSubjectDate = req.body.projectSubjectDate
        ? req.body.projectSubjectDate.length === 10 ?req.body.projectSubjectDate : convertToLocalDateString(req.body.projectSubjectDate)
        : null;
    req.body.projectMidDate = req.body.projectMidDate
      ? req.body.projectMidDate.length === 10 ?req.body.projectMidDate : convertToLocalDateString(req.body.projectMidDate)
      : null;
    req.body.projectFinalDate = req.body.projectFinalDate
      ? req.body.projectFinalDate.length === 10 ?req.body.projectFinalDate : convertToLocalDateString(req.body.projectFinalDate)
      : null;

    req.body.projectAppliedCostItems =
      req.body.projectAppliedCostItems?.length > 0
        ? JSON.stringify(req.body.projectAppliedCostItems)
        : null;
    delete req.body['action'];
    // let data = {}
    // for (const bodyKey in req.body) {
    //   if (req.body[bodyKey]) {
    //     // @ts-ignore
    //     data[bodyKey] = req.body[bodyKey]
    //   }
    // }
    // @ts-ignore
    const result = await ProjectService.updateProject({
      ...req.body,
      id: req.params.id,
    });

    res.status(200).json({
      data: result,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][updateProjectById][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    if (error.code === "ER_DUP_ENTRY") {
      res.status(500).json({
        message: "项目名称重复，请重新输入！",
      });
    } else {
      res.status(500).json({
        message: "项目信息更新失败！",
      });
    }
  }
};

/**
 * deletes a project
 *
 * @param req Express Request
 * @param res Express Response
 */
// @ts-ignore
export const deleteProjectById: RequestHandler = async (
  req: IDeleteProjectReq,
  res: Response
) => {
  try {
    const result = await ProjectService.deleteProject(req.params.id);

    res.status(200).json({
      data: result,
      code: 2000,
    })
  } catch (error) {
    console.error(
      "[projects.controller][deleteProjectById][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "项目信息删除失败！",
    });
  }
};

/**
 * upload an docs file for a project
 *
 * @param req Express Request
 * @param res Express Response
 */
// @ts-ignore
export const upload: RequestHandler = async (req: any, res: Response) => {
  try {
    console.log(req);
    let info = { status: "0", message: "上传文件成功", srcurl: "" };
    // 初始化处理文件对象
    var form = new IncomingForm();
    form.parse(req, function (error, fields, files) {
      if (error) {
        info.status = "1";
        info.message = "上传文件失败！";
        res.send(info);
      }

      const folderPath = "public/project/";
      if (!fs.existsSync(folderPath)) {
        fs.mkdirSync(folderPath);
      }
      const fullName = `${folderPath}${Date.now().toString()}_${
        files.file[0].originalFilename
      }`;
      fs.writeFileSync(`${fullName}`, fs.readFileSync(files.file[0].filepath)); // 存储文件到public静态资源文件夹下
      info.srcurl = fullName;
      res.send(info);
    });
  } catch (error) {
    console.error(
      "[machine.controller][deleteMachineById][Error] ",
      typeof error === "object" ? JSON.stringify(error) : error
    );
    res.status(500).json({
      message: "上传文件失败！",
    });
  }
};

